package com.cecil.generate.factory;


import com.cecil.generate.constants.CommonConstants;
import com.cecil.generate.constants.GlobalProperties;
import com.cecil.generate.domain.Column;
import com.cecil.generate.domain.Table;
import com.cecil.generate.exception.BusinessException;
import com.cecil.generate.service.DatabaseService;
import freemarker.template.Configuration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
@Component
public class MySQLFactory {

    @Autowired
    private GlobalProperties properties;
    @Autowired
    private DatabaseService databaseService;

    @Value("${spring.datasource.url}")
    private String url;
    @Autowired
    private DataSourceTransactionManagerAutoConfiguration dataSourceTransactionManagerAutoConfiguration;


    public void generate() {
        List<String> tableNames = properties.getTableNames();
        if (null == tableNames || tableNames.isEmpty()) {
            throw new BusinessException("请在application.yml中填写 global.table-names 配置");
        }

        String databaseName = url.substring(url.lastIndexOf(CommonConstants.SLASH) + 1);
        if (databaseName.contains(CommonConstants.QUESTION_MARK)) {
            databaseName = databaseName.substring(0, databaseName.indexOf(CommonConstants.QUESTION_MARK));
        }
        String dist = System.getProperty("user.dir") + "/src/main/java/" + properties.getBasePackage().replace(CommonConstants.DOT, File.separator);
        log.info("dist:{}", dist);

        List<String> baseEntityProperties = Arrays.asList("id", "create_by", "create_time", "update_by", "update_time", "deleted", "delete_time", "version");
        HashMap<String, String> javaTypeMap = properties.getJavaTypeMap();
        try {
            Set<String> javaTypeMapKey = javaTypeMap.keySet();
            List<Table> tables = databaseService.findByDbNameTableNames(databaseName, properties.getTableNames());
            for (Table table : tables) {
                List<Column> columns = databaseService.findColumn(databaseName, table.getTableName());
                columns = columns.stream().filter(i -> !baseEntityProperties.contains(i.getField())).toList();
                for (Column column : columns) {
                    String type = column.getType().toLowerCase();
                    String javaType = javaTypeMap.get(type);
                    if (null == javaType) {
                        String t = javaTypeMapKey.stream().filter(type::contains).findFirst().orElse(null);
                        if (null == t) {
                            javaType = "Object";
                            log.info("database type={} 没有匹配的javaType", type);
                        } else {
                            javaType = javaTypeMap.get(t);
                        }
                    }
                    log.info("table={}, column={}, javaType={}", table.getTableName(), column.getField(), javaType);
                    column.setJavaType(javaType);
                }
                table.setColumns(columns);
            }

            String author = properties.getAuthor();
            if (null == author || author.trim().isEmpty()) {
                author = System.getProperty("user.name");
            }
            String prefix = ResourceUtils.getURL("classpath:templates").getPath();
            LinkedHashMap<String, Object> map = new LinkedHashMap<>();
            map.put("packageName", properties.getBasePackage());
            map.put("module", properties.getModule());
            map.put("author", author);

            Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
            cfg.setEncoding(Locale.CHINA, StandardCharsets.UTF_8.name());
            cfg.setDirectoryForTemplateLoading(new File(prefix));

            for (ClassTypeEnum classTypeEnum : ClassTypeEnum.javaTemplates()) {
                classTypeEnum.generate(dist, cfg, tables, map, properties);
            }

            ClassTypeEnum.MAPPER_XML.generate(System.getProperty("user.dir") + "/src/main/resources/mapper/", cfg, tables, map, properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
